/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.api.services;

import java.time.Duration;

/**
 * Bef功能Session管理。
 * <p>使用Farris开发的前端使用Bff和Bef开发后端时，系统可以自动处理，通常无需开发人员关注Session的创建和关闭。
 * java原生编码的功能调用Bef接口时，一般需要先创建Session，否则可能会引发异常编号为{@code GSP_ADP_BEF_2010}的
 * {@link com.inspur.edp.bef.api.exceptions.BefEngineException}异常。
 * 但是有时候会发现未创建session也可以正常调用Bef接口，这通常是因为你的调用方已经创建了session，例如：
 * <ul><li>通过内部服务调用进来，内部服务会自动创建session；
 * <li>前端请求调用进来，前端使用Farris开发自动创建了Session；</ul>
 * <p>如果你需要使用此接口创建Session，请务必仔细阅读{@link #createSession(Duration)}方法的文档。
 * <p>更多详细说明请<a href="https://open.inspuronline.com/iGIX/#/document/mddoc/docs-gsp-cloud-ds%2Fdev-guide-beta%2Fspecial-subject%2FBE-related%2FBefSession%E7%9A%84%E5%88%9B%E5%BB%BA%E4%B8%8E%E9%94%80%E6%AF%81%E6%8E%A5%E5%8F%A3%E8%AF%B4%E6%98%8E%E5%8F%8A%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9.md“>访问这里</a>查看。
 */
public interface IBefSessionManager {

   /**
    * 创建一个永不超时的Bef功能session。
    * @deprecated 此方法已不建议使用。请使用{@link #createSession(Duration)}
    *
    * @return 功能SessionId
    *
    * @see #createSession(Duration)
    */
   @Deprecated
   String createSession();

   /**
    * 创建Bef功能session。
    * <p>创建session之后，请务必确保最后会调用{@link #closeCurrentSession()}关闭。否则可能导致内存泄露甚至是系统崩溃。
    * 为了保证发生异常时也能执行{@link #closeCurrentSession()}，需要使用try-finally语句。以下是一个范例：
    * <blockquote><pre>
    *     SpringBeanUtils.getBean(IBefSessionManager.class).createSession(Duration.ofSeconds(5));
    *     try {
    *         IStandardLcp lcp = SpringBeanUtils.getBean(ILcpFactory.class).createLcp("xxx");
    *         lcp.retrieve("xxx");
    *         ...
    *     } finally {
    *       SpringBeanUtils.getBean(IBefSessionManager.class).closeCurrentSession();
    *     }
    * </pre></blockquote>
    * <p>{@code createSession()}与{@code createLcp()}方法的执行顺序也需要注意，必须先{@code createSession()}，再{@code createLcp()}。
    * <p>此外，session遵循谁创建谁关闭的原则，因此也不要错误关闭他人创建的session,
    * 这样可能引发{@link java.util.EmptyStackException}或
    * 异常编号为{@code GSP_ADP_BEF_2010}的{@link com.inspur.edp.bef.api.exceptions.BefEngineException}异常。
    * <p>大部分场景下，业务逻辑的执行时间是可预估的，推荐使用估计的执行时间乘以2作为{@code duration}参数。
    * 这样可由框架进一步保证Session可以被及时关闭。
    * <p>Session支持重复创建，例如：先创建一个Session其ID假设为A，再创建一个Session其ID为B，调用{@link #getCurrentSessionId()}得到的是B，
    * 此时调用{@link #closeCurrentSession()}，再调用{@link #getCurrentSessionId()}得到的变为A。
    *
    * @param duration session的有效时间, 如果session持续没有使用超过此时间后将被关闭。
    * @return 功能SessionId
    */
   String createSession(Duration duration);

   /** 关闭当前Session。创建session之后，请务必确保最后会调用此方法关闭。*/
   void closeCurrentSession();

   /**
    * 返回当前Session的SessionId
    *
    * @return 如果当前不存在Session则返回null，此方法不可能返回空字符串。
    */
   String getCurrentSessionId();
}
